package view.overlay;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import controller.GameControl;
import controller.SimpleMouseListener;

public class AssignableControlsOverlay extends ActiveOverlay {
	
	private List<ReassignListener> mReassignListeners;
	private Map<GameControl, Button> mAssignButtons;

	private Button mBackButton;
	
	public AssignableControlsOverlay() {
		mReassignListeners = new ArrayList<ReassignListener>();
		mAssignButtons = new HashMap<GameControl, Button>();
		mBackButton = new Button("Back");
		mBackButton.setListener(new SimpleMouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				exitMenu();
				
			}
			
		});
	}
	
	private void exitMenu() {
		for (ReassignListener rl : mReassignListeners) {
			rl.exit();
		}
	}

	@Override
	protected void paint(Graphics g) {
		
		// Draw a background color
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, getWidth(), getHeight());
		
		mBackButton.draw(g);
		
		for (GameControl gc : mAssignButtons.keySet()) {
			Button b = mAssignButtons.get(gc);
			
			if (b != null) {
				b.draw(g);
			}
		}
		
	}
	
	@Override
	public void onMouseClicked(MouseEvent e) {
		if (mBackButton.contains(e.getPoint())) {
			mBackButton.activate(e);
		}
		
		for (GameControl gc : mAssignButtons.keySet()) {
			Button b = mAssignButtons.get(gc);
			
			if (b.contains(e.getPoint())) {
				startReassign(gc);
			}
		}
	}

	@Override
	public Dimension getPreferredSize() {
		return (new Dimension(0, 0));
	}
	
	private void startReassign(GameControl ctrl) {
		// Get the button for it and
		Button btn = mAssignButtons.get(ctrl);
		
		btn.setHighlighted(true);
		
		// notify we are assigning
		for (ReassignListener list : mReassignListeners) {
			list.startReassign(ctrl);
		}
	}
	
	public void finishAssign(GameControl ctrl) {
		Button btn = mAssignButtons.get(ctrl);
		btn.setHighlighted(false);
		
		// Reset the the button
		btn.setText(getButtonString(ctrl));
	}
	
	private String getButtonString(GameControl gc) {
		return String.format("%s = %s", gc.getDescription(), KeyEvent.getKeyText(gc.getActionCode()));
	}
	
	public void setControls(List<GameControl> controls) {
		mAssignButtons.clear();
		
		for (GameControl ctrl : controls) {
			Button btn = new Button(getButtonString(ctrl));
			mAssignButtons.put(ctrl, btn);
		}
		
		// calculate bounds
		calculateButtonBounds();
	}
	
	@Override
	public void resize(int width, int height) {
		super.resize(width, height);
		
		calculateButtonBounds();
	}
	
	private void calculateButtonBounds() {

		int bottomBarPadding = 100;
		
		int buttonWidth = 250;
		int buttonHeight = 50;
		
		int buttonVertPadding = 10;
		int buttonHorizPadding = 20;
		
		int xOffset = buttonHorizPadding;
		int yOffset = buttonVertPadding;
		
		int width = this.getWidth();
		int height = this.getHeight();
		
		// Add the buttons again
		for (GameControl gc : mAssignButtons.keySet()) {
			if (gc == null) continue;
			
			// Create a button
			Button b = mAssignButtons.get(gc);
			
			if (b == null) continue;
			
			b.setBounds(xOffset, yOffset, buttonWidth, buttonHeight);
			
			// Increments
			yOffset += buttonHeight + buttonVertPadding;
			if (yOffset + buttonHeight + buttonVertPadding > height - bottomBarPadding) {
				// reset y and increment x
				yOffset = buttonVertPadding;
				xOffset += buttonWidth + buttonHorizPadding;
			}
		}
		
		// calculate back button
		buttonWidth = 100;
		buttonHeight = 50;
		mBackButton.setBounds(width / 2 - buttonWidth / 2,
								height - buttonHeight - buttonVertPadding,
								buttonWidth,
								buttonHeight);
	}
	
	public void register(ReassignListener listener) {
		mReassignListeners.add(listener);
	}
	
	public void unregiser(ReassignListener listener) {
		mReassignListeners.remove(listener);
	}
	
	public interface ReassignListener {
		public void startReassign(GameControl control);
		public void exit();
	}
	
	

}
